package com.cdk8s.tkey.server.service.impl;

import com.bcw.sso.common.util.AESUtil;
import com.bcw.sso.model.dto.SsoClientRedisDO;
import com.bcw.sso.model.dto.SsoCommonUser;
import com.cdk8s.tkey.server.exception.OauthApiException;
import com.cdk8s.tkey.server.mapper.LoginAccountMapper;
import com.cdk8s.tkey.server.pojo.dto.param.OauthFormLoginParam;
import com.cdk8s.tkey.server.pojo.entity.LoginAccount;
import com.cdk8s.tkey.server.service.LoginAccountService;
import com.cdk8s.tkey.server.util.JsonUtil;
import com.cdk8s.tkey.server.util.SsoUserPwdUtil;
import com.cdk8s.tkey.server.util.okhttp.OkHttpResponse;
import com.cdk8s.tkey.server.util.okhttp.OkHttpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 登录账户服务
 *
 * @author ying
 */
@Service
@Slf4j
public class LoginAccountServiceImpl implements LoginAccountService {

    @Autowired
    private LoginAccountMapper loginAccountMapper;
    @Autowired
    private OkHttpService okHttpService;

    @Override
    public SsoCommonUser findLoginAccount(String username, String password) {
        List<LoginAccount> loginAccounts = loginAccountMapper.findForLogin(username);

        switch (loginAccounts.size()) {
            case 1:
                SsoCommonUser user = new SsoCommonUser();
                LoginAccount loginAccount = loginAccounts.get(0);

                user.setUsername(loginAccount.getUsername());
                return user;
            case 0:
                // TODO: 当前账户不存在，检查请求来源客户端是否存在。该功能得客户端支持查询。
            default:
                throw new OauthApiException("相同用户名存在多个！");
        }
    }

    @Override
    public SsoCommonUser findLoginAccount(OauthFormLoginParam oauthFormLoginParam, SsoClientRedisDO ssoClientToRedisBO) {
        if (oauthFormLoginParam == null || StringUtils.isEmpty(oauthFormLoginParam.getUsername())) {
            throw new OauthApiException("登录参数异常！");
        }

        String username = oauthFormLoginParam.getUsername();

        List<LoginAccount> loginAccounts = loginAccountMapper.findForLogin(username);

        String metaPassword = oauthFormLoginParam.getPassword();
        switch (loginAccounts.size()) {
            case 1:
                /* 计算并校验账户有效性，如：密码是否一致 */
                LoginAccount loginAccount = loginAccounts.get(0);

                String hashPwd = SsoUserPwdUtil.encryptPwd(loginAccount.getUsername(), metaPassword);
                if (hashPwd.equals(loginAccount.getSsoPassword())) {
                    SsoCommonUser user = new SsoCommonUser();
                    user.setUsername(loginAccount.getUsername());
                    return user;
                } else {
                    throw new OauthApiException("用户名或密码不正确！");
                }
            case 0:
                try {
                    // 当前账户不存在，若请求来源客户端支持登录账户回查确认，将远程校验当前登录账户是否有效，若有效，将自动创建该用户。
                    if (ssoClientToRedisBO != null && ssoClientToRedisBO.getId() > 0
                            && !StringUtils.isEmpty(ssoClientToRedisBO.getClientCheckLoginUserUrl())) {
                        Map<String, String> params = new HashMap<>();
                        params.put("username", username);
                        // 以用户名作为种子，对密码加密。
                        params.put("password", AESUtil.encrypt(metaPassword, username));

                        Map<String, String> headers = new HashMap<>();


                        String rebackCheckURL = ssoClientToRedisBO.getClientCheckLoginUserUrl();
                        // FIXME : 发送远程访问，可能被远程请求拖死，这里最好要做个超时和异常处理。
                        OkHttpResponse okHttpResponse = okHttpService.post(rebackCheckURL, params, headers);

                        if (okHttpResponse.getStatus() == HttpStatus.OK.value()) {
                            String response = okHttpResponse.getResponse();
                            SsoCommonUser ssoCommonUser = JsonUtil.toObject(response, SsoCommonUser.class);
                            if (ssoCommonUser != null) {
                                /* 新增登录账户 */
                                LoginAccount la = new LoginAccount();
                                BeanUtils.copyProperties(ssoCommonUser, la);
                                la.setFromClientId(ssoClientToRedisBO.getId());
                                // 这里获取加密密码，不能直接用 username ，因为它可能是其他能登录的信息，如手机号。
                                la.setSsoPassword(SsoUserPwdUtil.encryptPwd(ssoCommonUser.getUsername(), metaPassword));
                                la.setStatus("有效");

                                int rst = loginAccountMapper.insert(la);
                                log.debug("Add login account " + rst);
                            }
                            return ssoCommonUser;
                        }
                    }
                } catch (Exception e) {
                    log.error("回访客户端用户校验异常。", e);
                }

                // 上述处理都无法获取有效数据时
                throw new OauthApiException("您使用的账户不存在！");
            default:
                throw new OauthApiException("相同用户名存在多个！请联系管理员处理！");
        }
    }

}
